﻿using _2DLineCamera.Models;
using IKapBoardClassLibrary;
using IKapC.NET;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace _2DLineCamera.IKCamera
{

    public class LineTriggerCamera
    {
        Config configfil = new Config();
        Tool tool = new Tool();
        public uint CameraCount=0;
        IKDevice pDev = new IKDevice();

        // 设备类型枚举
        enum IKDeviceType
        {
            DEVICE_NIL = 0,
            DEVICE_CML,
            DEVICE_CXP,
            DEVICE_USB,
            DEVICE_GIGEVISION
        }

        // 设备信息结构体
        struct IKDeviceInfo
        {
            public IKDeviceType nType;
            public int nDevIndex;
            public int nBoardIndex;
            public string sDevName;
        }
        private List<IKDeviceInfo> m_listDeviceInfo = new List<IKDeviceInfo>();

        // 相机设备句柄。
        //
        // Camera device handle.
        public IntPtr m_hCameraL = new IntPtr(-1);
        public IntPtr m_hCameraR = new IntPtr(-1);

        // 采集卡设备句柄。
        //
        // Frame grabber device handle.
        public IntPtr m_hBoardL = new IntPtr(-1);
        public IntPtr m_hBoardR = new IntPtr(-1);

        // 保存图像的文件名。
        //
        // File name of image.
        public string m_strFileName = "C:\\CSharpImage.tif";

        // 当前帧索引。
        //
        // Current frame index.
        public int m_nCurFrameIndexL = 0;
        public int m_nCurFrameIndexR = 0;
        // 图像缓冲区申请的帧数。
        //
        // The number of frames requested by buffer.
        public int m_nTotalFrameCountL = 5;
        public int m_nTotalFrameCountR = 5;
        /* @brief：判断 IKapC 函数是否成功调用。
         * @param[in] res：函数返回值。
         *
         * @brief：Determine whether the IKapC function is called successfully.
         * @param[in] res：Function return value. */
        static void CheckIKapC(uint res)
        {
            if (res != (uint)ItkStatusErrorId.ITKSTATUS_OK)
            {
                Console.Error.WriteLine("Error Code: {0}.\n", res.ToString("x8"));
                IKapCLib.ItkManTerminate();
                Console.ReadLine();
                MessageBox.Show("异常！" + res.ToString("x8"));
            }
        }

        /* @brief：判断 IKapBoard 函数是否成功调用。
         * @param[in] ret：函数返回值。
         *
         * @brief：Determine whether the IKapBoard function is called successfully.
         * @param[in] ret：Function return value. */
        static void CheckIKapBoard(int ret)
        {
            if (ret != (int)ErrorCode.IK_RTN_OK)
            {
                string sErrMsg = "";
                IKapBoard.IKAPERRORINFO tIKei = new IKapBoardClassLibrary.IKapBoard.IKAPERRORINFO();

                // 获取错误码信息。
                //
                // Get error code message.
                IKapBoard.IKapGetLastError(ref tIKei, true);

                // 打印错误信息。
                //
                // Print error message.
                sErrMsg = string.Concat("Error",
                                        sErrMsg,
                                        "Board Type\t = 0x", tIKei.uBoardType.ToString("X4"), "\n",
                                        "Board Index\t = 0x", tIKei.uBoardIndex.ToString("X4"), "\n",
                                        "Error Code\t = 0x", tIKei.uErrorCode.ToString("X4"), "\n"
                                        );
                Console.Write(sErrMsg);
                Console.ReadLine();
                MessageBox.Show("异常！"+sErrMsg);   
            }
        }

        #region Callback
        public delegate void IKapCallBackProc(IntPtr pParam);

        /* @brief：本函数被注册为一个回调函数。当图像采集开始时，函数被调用。
         *
         * @brief：This function is registered as a callback function. When starting grabbing images, the function will be called. */
        private IKapCallBackProc OnGrabStartProc;

        /* @brief：本函数被注册为一个回调函数。当采集丢帧时，函数被调用。
         *
         * @brief：This function is registered as a callback function. When grabbing frame lost, the function will be called. */
        private IKapCallBackProc OnFrameLostProc;

        /* @brief：本函数被注册为一个回调函数。当图像采集超时时，函数被调用。
         *
         * @brief：This function is registered as a callback function. When grabbing images time out, the function will be called. */
        private IKapCallBackProc OnTimeoutProc;

        /* @brief：本函数被注册为一个回调函数。当一帧图像采集完成时，函数被调用。
         *
         * @brief：This function is registered as a callback function. When a frame of image grabbing ready, the function will be called. */
        private IKapCallBackProc OnFrameReadyProcL;
        private IKapCallBackProc OnFrameReadyProcR;

        /* @brief：本函数被注册为一个回调函数。当图像采集停止时，函数被调用。
         *
         * @brief：This function is registered as a callback function. When stopping grabbing images, the function will be called. */
        private IKapCallBackProc OnGrabStopProc;
        #endregion

        #region Callback
        /* @brief：本函数被注册为一个回调函数。当图像采集开始时，函数被调用。
         * @param[in] pParam：输入参数。
         *
         * @brief：This function is registered as a callback function. When starting grabbing images, the function will be called.
         * @param[in] pParam：Input parameter. */
        public void OnGrabStartFunc(IntPtr pParam)
        {
            Console.WriteLine("Start grabbing image");
        }

        /* @brief：本函数被注册为一个回调函数。当采集丢帧时，函数被调用。
         * @param[in] pParam：输入参数。
         *
         * @brief：This function is registered as a callback function. When grabbing frame lost, the function will be called.
         * @param[in] pParam：Input parameter. */
        public void OnFrameLostFunc(IntPtr pParam)
        {
            Console.WriteLine("Image frame lost");
        }

        /* @brief：本函数被注册为一个回调函数。当图像采集超时时，函数被调用。
         * @param[in] pParam：输入参数。
         *
         * @brief：This function is registered as a callback function. When grabbing images time out, the function will be called.
         * @param[in] pParam：Input parameter. */
        public void OnTimeoutFunc(IntPtr pParam)
        {
            Console.WriteLine("Grab image timeout");
        }

        /* @brief：本函数被注册为一个回调函数。当一帧图像采集完成时，函数被调用。
         * @param[in] pParam：输入参数。
         *
         * @brief：This function is registered as a callback function. When a frame of image grabbing ready, the function will be called.
         * @param[in] pParam：Input parameter. */
        //public void OnFrameReadyFunc(IntPtr pParam)
        //{
        //    Console.WriteLine("Grab frame ready");

        //    IntPtr hDev = (IntPtr)pParam;
        //    IntPtr pUserBuffer = IntPtr.Zero;
        //    int nFrameSize = 0;
        //    int nFrameCount = 0;
        //    IKapBoard.IKAPBUFFERSTATUS status = new IKapBoard.IKAPBUFFERSTATUS();

        //    IKapBoard.IKapGetInfo(hDev, (uint)INFO_ID.IKP_FRAME_COUNT, ref nFrameCount);
        //    IKapBoard.IKapGetBufferStatus(hDev, m_nCurFrameIndex, ref status);

        //    // 当图像缓冲区满时。
        //    //
        //    // When the buffer is full.
        //    if (status.uFull == 1)
        //    {
        //        // 获取一帧图像的大小。
        //        //
        //        // Get the size of a frame of image.
        //        IKapBoard.IKapGetInfo(hDev, (uint)INFO_ID.IKP_FRAME_SIZE, ref nFrameSize);

        //        // 获取缓冲区地址。
        //        //
        //        // Get the buffer address.
        //        IKapBoard.IKapGetBufferAddress(hDev, m_nCurFrameIndex, ref pUserBuffer);

        //        // 保存图像。
        //        //
        //        // Save image.

        //        IKapBoard.IKapSaveBuffer(hDev, m_nCurFrameIndex, m_strFileName, (int)ImageCompressionFalg.IKP_DEFAULT_COMPRESSION);

        //    }
        //    m_nCurFrameIndex++;
        //    m_nCurFrameIndex = m_nCurFrameIndex % m_nTotalFrameCount;
        //}

        /* @brief：本函数被注册为一个回调函数。当图像采集停止时，函数被调用。
         * @param[in] pParam：输入参数。
         *
         * @brief：This function is registered as a callback function. When stopping grabbing images, the function will be called.
         * @param[in] pParam：Input parameter. */
        public void OnGrabStopFunc(IntPtr pParam)
        {
            Console.WriteLine("Stop grabbing image");
        }
        #endregion

        #region member function

        /* @brief：初始化IKapC 运行环境。
         *
         * @brief：Initialize IKapC runtime environment. */
        public void InitEnvironment()
        {
            // IKapC 函数返回值。
            //
            // Return value of IKapC functions.
            uint res = (uint)ItkStatusErrorId.ITKSTATUS_OK;

            res = IKapCLib.ItkManInitialize();
            CheckIKapC(res);
        }

        /* @brief：释放 IKapC 运行环境。
         *
         * @brief：Release IKapC runtime environment. */
        public void ReleaseEnvironment()
        {
            IKapCLib.ItkManTerminate();
        }

        /* @brief：配置相机设备。
         *
         * @brief：Configure camera device. */
        public Config ConfigureCamera()
        {
            uint res = (uint)ItkStatusErrorId.ITKSTATUS_OK;
            uint numCameras = 0;

            // 枚举可用相机的数量。在打开相机前，必须调用 ItkManGetDeviceCount() 函数。
            //
            // Enumerate the number of available cameras. Before opening the camera, ItkManGetDeviceCount() function must be called.
            res = IKapCLib.ItkManGetDeviceCount(ref numCameras);
            CheckIKapC(res);

            // 当没有连接的相机时。
            //
            // When there is no connected cameras.
            if (numCameras == 0)
            {
                Console.Write("No camera.\n");
                IKapCLib.ItkManTerminate();
                Console.ReadLine();
                Environment.Exit(1);
            }

            // 打开CameraLink相机。
            //
            // Open CameraLink camera.
            for (uint i = 0; i < numCameras; i++)
            {
                IKapCLib.ITKDEV_INFO di = new IKapCLib.ITKDEV_INFO();

                // 获取相机设备信息。
                //
                // Get camera device information.
                res = IKapCLib.ItkManGetDeviceInfo(i, ref di);
                Console.Write("Using camera: serial: {0}, name: {1}, interface: {2}.\n", di.SerialNumber, di.FullName, di.DeviceClass);
                
                // 当设备为 CameraLink 相机且序列号正确时。
                //
                // When the device is CameraLink camera and the serial number is proper.
                if (di.DeviceClass == "CameraLink" && di.SerialNumber != "")
                {
                    IKapCLib.ITK_CL_DEV_INFO cl_board_info = new IKapCLib.ITK_CL_DEV_INFO();

                    // 打开相机。
                    //
                    // Open camera.
                    res = IKapCLib.ItkDevOpen(i, (int)ItkDeviceAccessMode.ITKDEV_VAL_ACCESS_MODE_EXCLUSIVE, ref m_hCameraL);
                    CheckIKapC(res);

                    // 获取 CameraLink 相机设备信息。
                    //
                    // Get CameraLink camera device information.
                    res = IKapCLib.ItkManGetCLDeviceInfo(i, ref cl_board_info);
                    CheckIKapC(res);

                    // 打开采集卡。
                    //
                    // Open frame grabber.
                    m_hBoardL = IKapBoard.IKapOpen(cl_board_info.HostInterface, cl_board_info.BoardIndex);
                    if (m_hBoardL.Equals(-1))
                        CheckIKapBoard((int)ErrorCode.IKStatus_OpenBoardFail);

                    break;
                }
            }
            return configfil;
        }

        /* @brief：配置采集卡设备。
         *
         * @brief：Configure frame grabber device. */
        public bool ConfigureFrameGrabber(IKapCallBackProc ProcessImage, bool Manual_control, string SerialNumber, string Manualpath)
        {
            int ret = (int)ErrorCode.IK_RTN_OK;
            string configFileName = "";
            configfil = tool.ReadConfigFile();
            bool OpenConfigOK = true;
            // 导入配置文件。
            //
            // Load configuration file.
            if (Manual_control == true)
            {
                if (Manualpath == "Left")
                {
                    configFileName = GetOption();
                    if (configFileName != null)
                    {
                        DialogResult result = MessageBox.Show("是否需要保存配置文件路径" + configFileName, "提示", MessageBoxButtons.YesNoCancel);
                        if (result == DialogResult.Yes)
                        {
                            configfil.LeftConfigurationfilepath = configFileName;

                            tool.SaveConfigFile(configfil);
                        }
                    }
                }
                if (Manualpath == "Right")
                {
                    configFileName = GetOption();
                    if (configFileName != null)
                    {
                        DialogResult result = MessageBox.Show("是否需要保存配置文件路径" + configFileName, "提示", MessageBoxButtons.YesNoCancel);
                        if (result == DialogResult.Yes)
                        {
                            configfil.RightConfigurationfilepath = configFileName;

                            tool.SaveConfigFile(configfil);
                        }
                    }
                }
            }
            else
            {
                if (Manualpath == "Left")
                {
                    configFileName = configfil.LeftConfigurationfilepath;
                }
                if (Manualpath == "Right")
                {
                    configFileName = configfil.RightConfigurationfilepath;
                }
            }
            if (configFileName == null || CameraCount == 0)
            {
                Console.WriteLine("Fail to get configuration, using default setting!\n");
                return false;
            }
            else
            {
                if (Manualpath == "Left")
                {
                    for (int i = 0; i < configfil.CameraNames.Count; i++)
                    {
                        if (SerialNumber == configfil.CameraNames[i].SerialNumber)
                        {
                            //pDev.loadConfiguration(configFileName);
                            ret = IKapBoard.IKapLoadConfigurationFromFile(m_hBoardL, configFileName);
                            CheckIKapBoard(ret);
                            if (ret != (int)ErrorCode.IK_RTN_OK)
                            {
                                OpenConfigOK = false;
                            }
                            // 设置图像缓冲区帧数。
                            //
                            // Set frame count of buffer.
                            ret = IKapBoard.IKapSetInfo(m_hBoardL, (uint)INFO_ID.IKP_FRAME_COUNT, m_nTotalFrameCountL);
                            CheckIKapBoard(ret);
                            if (ret != (int)ErrorCode.IK_RTN_OK)
                            {
                                OpenConfigOK = false;
                            }
                            // 设置超时时间。
                            //
                            // Set time out time.
                            int timeout = -1;
                            ret = IKapBoard.IKapSetInfo(m_hBoardL, (uint)INFO_ID.IKP_TIME_OUT, timeout);
                            CheckIKapBoard(ret);
                            if (ret != (int)ErrorCode.IK_RTN_OK)
                            {
                                OpenConfigOK = false;
                            }
                            // 设置采集模式。
                            //
                            // Set grab mode.
                            int grab_mode = (int)GrabMode.IKP_GRAB_NON_BLOCK;
                            ret = IKapBoard.IKapSetInfo(m_hBoardL, (uint)INFO_ID.IKP_GRAB_MODE, grab_mode);
                            CheckIKapBoard(ret);
                            if (ret != (int)ErrorCode.IK_RTN_OK)
                            {
                                OpenConfigOK = false;
                            }
                            // 设置传输模式。
                            //
                            // Set transfer mode.
                            int transfer_mode = (int)FrameTransferMode.IKP_FRAME_TRANSFER_SYNCHRONOUS_NEXT_EMPTY_WITH_PROTECT;
                            ret = IKapBoard.IKapSetInfo(m_hBoardL, (uint)INFO_ID.IKP_FRAME_TRANSFER_MODE, transfer_mode);
                            CheckIKapBoard(ret);
                            if (ret != (int)ErrorCode.IK_RTN_OK)
                            {
                                OpenConfigOK = false;
                            }
                            // 注册回调函数
                            //
                            // Register callback functions.
                            //OnGrabStartProc = new IKapCallBackProc(OnGrabStartFunc);
                            //ret = IKapBoard.IKapRegisterCallback(m_hBoardL, (uint)CallBackEvents.IKEvent_GrabStart, Marshal.GetFunctionPointerForDelegate(OnGrabStartProc), m_hBoardL);
                            //CheckIKapBoard(ret);
                            OnFrameReadyProcL = new IKapCallBackProc(ProcessImage);
                            ret = IKapBoard.IKapRegisterCallback(m_hBoardL, (uint)CallBackEvents.IKEvent_FrameReady, Marshal.GetFunctionPointerForDelegate(OnFrameReadyProcL), m_hBoardL);
                            CheckIKapBoard(ret);
                            //OnFrameLostProc = new IKapCallBackProc(OnFrameLostFunc);
                            //ret = IKapBoard.IKapRegisterCallback(m_hBoardL, (uint)CallBackEvents.IKEvent_FrameLost, Marshal.GetFunctionPointerForDelegate(OnFrameLostProc), m_hBoardL);
                            //CheckIKapBoard(ret);
                            //OnTimeoutProc = new IKapCallBackProc(OnTimeoutFunc);
                            //ret = IKapBoard.IKapRegisterCallback(m_hBoardL, (uint)CallBackEvents.IKEvent_TimeOut, Marshal.GetFunctionPointerForDelegate(OnTimeoutProc), m_hBoardL);
                            //CheckIKapBoard(ret);
                            //OnGrabStopProc = new IKapCallBackProc(OnGrabStopFunc);
                            //ret = IKapBoard.IKapRegisterCallback(m_hBoardL, (uint)CallBackEvents.IKEvent_GrabStop, Marshal.GetFunctionPointerForDelegate(OnGrabStopProc), m_hBoardL);
                            //CheckIKapBoard(ret);
                            return OpenConfigOK;
                        }
                    }
                }
                if (Manualpath == "Right")
                {
                    for (int i = 0; i < configfil.CameraNames.Count; i++)
                    {
                        if (SerialNumber == configfil.CameraNames[i].SerialNumber)
                        {
                            //pDev.loadConfiguration(configFileName);
                            ret = IKapBoard.IKapLoadConfigurationFromFile(m_hBoardR, configFileName);
                            CheckIKapBoard(ret);
                            if (ret != (int)ErrorCode.IK_RTN_OK)
                            {
                                OpenConfigOK = false;
                            }
                            // 设置图像缓冲区帧数。
                            //
                            // Set frame count of buffer.
                            ret = IKapBoard.IKapSetInfo(m_hBoardR, (uint)INFO_ID.IKP_FRAME_COUNT, m_nTotalFrameCountR);
                            CheckIKapBoard(ret);
                            if (ret != (int)ErrorCode.IK_RTN_OK)
                            {
                                OpenConfigOK = false;
                            }
                            // 设置超时时间。
                            //
                            // Set time out time.
                            int timeout = -1;
                            ret = IKapBoard.IKapSetInfo(m_hBoardR, (uint)INFO_ID.IKP_TIME_OUT, timeout);
                            CheckIKapBoard(ret);
                            if (ret != (int)ErrorCode.IK_RTN_OK)
                            {
                                OpenConfigOK = false;
                            }
                            // 设置采集模式。
                            //
                            // Set grab mode.
                            int grab_mode = (int)GrabMode.IKP_GRAB_NON_BLOCK;
                            ret = IKapBoard.IKapSetInfo(m_hBoardR, (uint)INFO_ID.IKP_GRAB_MODE, grab_mode);
                            CheckIKapBoard(ret);
                            if (ret != (int)ErrorCode.IK_RTN_OK)
                            {
                                OpenConfigOK = false;
                            }
                            // 设置传输模式。
                            //
                            // Set transfer mode.
                            int transfer_mode = (int)FrameTransferMode.IKP_FRAME_TRANSFER_SYNCHRONOUS_NEXT_EMPTY_WITH_PROTECT;
                            ret = IKapBoard.IKapSetInfo(m_hBoardR, (uint)INFO_ID.IKP_FRAME_TRANSFER_MODE, transfer_mode);
                            CheckIKapBoard(ret);
                            if (ret != (int)ErrorCode.IK_RTN_OK)
                            {
                                OpenConfigOK = false;
                            }
                            // 注册回调函数
                            //
                            // Register callback functions.
                            //OnGrabStartProc = new IKapCallBackProc(OnGrabStartFunc);
                            //ret = IKapBoard.IKapRegisterCallback(m_hBoardL, (uint)CallBackEvents.IKEvent_GrabStart, Marshal.GetFunctionPointerForDelegate(OnGrabStartProc), m_hBoardR);
                            //CheckIKapBoard(ret);
                            OnFrameReadyProcR = new IKapCallBackProc(ProcessImage);
                            ret = IKapBoard.IKapRegisterCallback(m_hBoardR, (uint)CallBackEvents.IKEvent_FrameReady, Marshal.GetFunctionPointerForDelegate(OnFrameReadyProcR), m_hBoardR);
                            CheckIKapBoard(ret);
                            //    OnFrameLostProc = new IKapCallBackProc(OnFrameLostFunc);
                            //    ret = IKapBoard.IKapRegisterCallback(m_hBoardL, (uint)CallBackEvents.IKEvent_FrameLost, Marshal.GetFunctionPointerForDelegate(OnFrameLostProc), m_hBoardR);
                            //    CheckIKapBoard(ret);
                            //    OnTimeoutProc = new IKapCallBackProc(OnTimeoutFunc);
                            //    ret = IKapBoard.IKapRegisterCallback(m_hBoardL, (uint)CallBackEvents.IKEvent_TimeOut, Marshal.GetFunctionPointerForDelegate(OnTimeoutProc), m_hBoardR);
                            //    CheckIKapBoard(ret);
                            //    OnGrabStopProc = new IKapCallBackProc(OnGrabStopFunc);
                            //    ret = IKapBoard.IKapRegisterCallback(m_hBoardL, (uint)CallBackEvents.IKEvent_GrabStop, Marshal.GetFunctionPointerForDelegate(OnGrabStopProc), m_hBoardR);
                            //    CheckIKapBoard(ret);
                            return OpenConfigOK;
                        }
                    }
                }
            }


            return OpenConfigOK;
        }

        /* @brief：设置帧触发参数。
         *
         * @brief：Set frame trigger parameters. */
        public void SetFrameTrigger()
        {
            if (CameraCount==0)
            {
                return;
            }
            uint res = (uint)ItkStatusErrorId.ITKSTATUS_OK;
            int ret = (int)ErrorCode.IK_RTN_OK;

            // 设置采集卡触发模式。
            //
            // Set frame grabber trigger mode.
            ret = IKapBoard.IKapSetInfo(m_hBoardL, (uint)INFO_ID.IKP_BOARD_TRIGGER_MODE, (int)BoardTriggerMode.IKP_BOARD_TRIGGER_MODE_VAL_OUTTER);
            CheckIKapBoard(ret);
            ret = IKapBoard.IKapSetInfo(m_hBoardR, (uint)INFO_ID.IKP_BOARD_TRIGGER_MODE, (int)BoardTriggerMode.IKP_BOARD_TRIGGER_MODE_VAL_OUTTER);
            CheckIKapBoard(ret);

            // 设置采集卡触发源。
            //
            // Set frame grabber trigger source.
            ret = IKapBoard.IKapSetInfo(m_hBoardL, (uint)INFO_ID.IKP_BOARD_TRIGGER_SOURCE, (int)BoardTriggerSource.IKP_BOARD_TRIGGER_SOURCE_VAL_GENERAL_INPUT1);
            CheckIKapBoard(ret);
            ret = IKapBoard.IKapSetInfo(m_hBoardR, (uint)INFO_ID.IKP_BOARD_TRIGGER_SOURCE, (int)BoardTriggerSource.IKP_BOARD_TRIGGER_SOURCE_VAL_GENERAL_INPUT1);
            CheckIKapBoard(ret);

            // 设置同步模式。
            //
            // Set synchronization mode.
            string syncName = "SynchronizationMode";
            string syncParameter = "InternalFreeRun";
            res = IKapCLib.ItkDevFromString(m_hCameraL, syncName, syncParameter);
            res = IKapCLib.ItkDevFromString(m_hCameraR, syncName, syncParameter);
            CheckIKapC(res);
        }

        /* @brief：清除回调函数。
         *
         * @brief：Unregister callback functions. */
        public void UnRegisterCallback()
        {
            int ret = (int)ErrorCode.IK_RTN_OK;

            ret = IKapBoard.IKapUnRegisterCallback(m_hBoardL, (uint)CallBackEvents.IKEvent_GrabStart);
            ret = IKapBoard.IKapUnRegisterCallback(m_hBoardL, (uint)CallBackEvents.IKEvent_FrameReady);
            ret = IKapBoard.IKapUnRegisterCallback(m_hBoardL, (uint)CallBackEvents.IKEvent_FrameLost);
            ret = IKapBoard.IKapUnRegisterCallback(m_hBoardL, (uint)CallBackEvents.IKEvent_TimeOut);
            ret = IKapBoard.IKapUnRegisterCallback(m_hBoardL, (uint)CallBackEvents.IKEvent_GrabStop);

            ret = IKapBoard.IKapUnRegisterCallback(m_hBoardR, (uint)CallBackEvents.IKEvent_GrabStart);
            ret = IKapBoard.IKapUnRegisterCallback(m_hBoardR, (uint)CallBackEvents.IKEvent_FrameReady);
            ret = IKapBoard.IKapUnRegisterCallback(m_hBoardR, (uint)CallBackEvents.IKEvent_FrameLost);
            ret = IKapBoard.IKapUnRegisterCallback(m_hBoardR, (uint)CallBackEvents.IKEvent_TimeOut);
            ret = IKapBoard.IKapUnRegisterCallback(m_hBoardR, (uint)CallBackEvents.IKEvent_GrabStop);
        }

        /* @brief：关闭设备。
         *
         * @brief：Close device. */
        public void CloseDevice()
        {
            // 关闭采集卡设备。
            //
            // Close frame grabber device.
            if (!m_hBoardL.Equals(-1))
            {
                IKapBoard.IKapClose(m_hBoardL);
                m_hBoardL = (IntPtr)(-1);
            }
            if (!m_hBoardR.Equals(-1))
            {
                IKapBoard.IKapClose(m_hBoardR);
                m_hBoardR = (IntPtr)(-1);
            }

            // 关闭相机设备。
            //
            // Close camera device.
            if (!m_hCameraL.Equals(-1))
            {
                IKapCLib.ItkDevClose(m_hCameraL);
                m_hCameraL = (IntPtr)(-1);
            }
            if (!m_hCameraR.Equals(-1))
            {
                IKapCLib.ItkDevClose(m_hCameraR);
                m_hCameraR = (IntPtr)(-1);
            }
        }

        /* @brief：选择用户配置文件。
         *
         * @brief：Select configuration file. */
        public string GetOption()
        {
            string vlcfFileName = null;
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "vlcf文件(*.vlcf)|*.vlcf|所有文件(*.*)|*.*";
            ofd.FilterIndex = 1;
            ofd.Title = "选择打开文件";
            DialogResult result = ofd.ShowDialog();
            if (result == DialogResult.OK)
            {
                vlcfFileName = ofd.FileName;
                return vlcfFileName;
            }
            if (result == DialogResult.No)
            {
                return null;
            }
            return null;
        }
        #endregion

        public uint detectDevice(bool Manual_control)
        {
            configfil = tool.ReadConfigFile();
            m_listDeviceInfo.Clear();
            uint nDevCount = 0;
            uint res = IKapCLib.ItkManGetDeviceCount(ref nDevCount);
            CameraCount = nDevCount;
            if (Manual_control == false)
            {

                if (res != (uint)ItkStatusErrorId.ITKSTATUS_OK)
                    return 0;
                string[] CameraName = new string[nDevCount];
                IKapCLib.ITKDEV_INFO pDevInfo = new IKapCLib.ITKDEV_INFO();
                IKapCLib.ITK_CL_DEV_INFO pClDevInfo = new IKapCLib.ITK_CL_DEV_INFO();
                IKapCLib.ITK_CXP_DEV_INFO pCxpDevInfo = new IKapCLib.ITK_CXP_DEV_INFO();
                IKapCLib.ITKGIGEDEV_INFO pGvDevInfo = new IKapCLib.ITKGIGEDEV_INFO();

                for (uint i = 0; i < nDevCount; ++i)
                {
                    IkCameras ikCameras = new IkCameras();
                    IKDeviceInfo pInfo = new IKDeviceInfo();
                    IKapCLib.ItkManGetDeviceInfo(i, ref pDevInfo);

                    if (pDevInfo.DeviceClass.CompareTo("GigEVision") == 0)
                    {
                        return nDevCount;
                        res = IKapCLib.ItkManGetGigEDeviceInfo(i, ref pGvDevInfo);
                        if (res != (uint)ItkStatusErrorId.ITKSTATUS_OK)
                            return nDevCount;
                        pInfo.nType = IKDeviceType.DEVICE_GIGEVISION;
                        pInfo.nDevIndex = (int)i;
                        pInfo.nBoardIndex = -1;
                        pInfo.sDevName = pDevInfo.FullName;
                    }
                    else if (pDevInfo.DeviceClass.CompareTo("USB3Vision") == 0)
                    {
                        continue;
                    }
                    else if (pDevInfo.DeviceClass.CompareTo("CoaXPress") == 0)
                    {
                        res = IKapCLib.ItkManGetCXPDeviceInfo(i, ref pCxpDevInfo);
                        if (res != (uint)ItkStatusErrorId.ITKSTATUS_OK)
                            return nDevCount;
                        pInfo.nType = IKDeviceType.DEVICE_CXP;
                        pInfo.nDevIndex = (int)i;
                        pInfo.nBoardIndex = (int)pCxpDevInfo.BoardIndex;
                        pInfo.sDevName = pDevInfo.FullName;
                    }
                    else
                    {
                        res = IKapCLib.ItkManGetCLDeviceInfo(i, ref pClDevInfo);
                        //if (res != (uint)ItkStatusErrorId.ITKSTATUS_OK)
                        //    return;
                        pInfo.nType = IKDeviceType.DEVICE_CML;
                        pInfo.nDevIndex = (int)i;
                        pInfo.nBoardIndex = (int)pClDevInfo.BoardIndex;
                        pInfo.sDevName = pDevInfo.FullName;

                        if (configfil.CameraNames.Count > 0)
                        {
                            return nDevCount;
                        }
                        Console.WriteLine(pDevInfo.SerialNumber);
                        ikCameras.CameraName = pInfo.sDevName;
                        ikCameras.Cameran_nDevIndex = pInfo.nDevIndex;
                        ikCameras.Camera_nBoardIndex = pInfo.nBoardIndex;
                        ikCameras.Camera_nType = (int)pInfo.nType;
                        ikCameras.SerialNumber = pDevInfo.SerialNumber;

                        configfil.CameraNames.Add(ikCameras);
                        tool.SaveConfigFile(configfil);
                    }
                }
            }
            return nDevCount;
        }
        public void JudgeCameraSerialNumber(string SerialNumber, string Manual)
        {
            configfil = tool.ReadConfigFile();
            uint res;
            if (Manual == "Left")
            {
                for (uint i = 0; i < configfil.CameraNames.Count; i++)
                {
                    if (configfil.CameraNames[(int)i].SerialNumber == SerialNumber)
                    {
                        switch (configfil.CameraNames[(int)i].Camera_nType)
                        {
                            case 4:
                                res = IKapCLib.ItkDevOpen((uint)configfil.CameraNames[(int)i].Cameran_nDevIndex, (int)(ItkDeviceAccessMode.ITKDEV_VAL_ACCESS_MODE_CONTROL), ref m_hCameraL);
                                CheckIKapC(res);
                                break;
                            case 1:
                                res = IKapCLib.ItkDevOpen((uint)configfil.CameraNames[(int)i].Cameran_nDevIndex, (int)(ItkDeviceAccessMode.ITKDEV_VAL_ACCESS_MODE_CONTROL), ref m_hCameraL);
                                CheckIKapC(res);
                                m_hBoardL = IKapBoard.IKapOpen((uint)BoardType.IKBoardPCIE, (uint)configfil.CameraNames[(int)i].Camera_nBoardIndex);
                                if (m_hBoardL.Equals(-1))
                                    CheckIKapBoard((int)ErrorCode.IKStatus_OpenBoardFail);
                                break;
                            case 2:
                                res = IKapCLib.ItkDevOpen((uint)configfil.CameraNames[(int)i].Cameran_nDevIndex, (int)(ItkDeviceAccessMode.ITKDEV_VAL_ACCESS_MODE_CONTROL), ref m_hCameraL);
                                CheckIKapC(res);
                                IKapCLib.ITK_CXP_DEV_INFO camInfo = new IKapCLib.ITK_CXP_DEV_INFO();
                                IKapBoard.IKAP_CXP_BOARD_INFO boaInfo = new IKapBoard.IKAP_CXP_BOARD_INFO();
                                res = IKapCLib.ItkManGetCXPDeviceInfo((uint)i, ref camInfo);
                                CheckIKapC(res);
                                boaInfo.BoardIndex = camInfo.BoardIndex;
                                boaInfo.CameraIndex = camInfo.CameraId;
                                boaInfo.MasterPort = camInfo.MasterPort;
                                boaInfo.SlaveCount = camInfo.SlaveCount;

                                boaInfo.Reserved = new byte[252];
                                for (int j = 0; j < camInfo.Reserved.Length; j++)
                                {
                                    boaInfo.Reserved[j] = (byte)camInfo.Reserved.ElementAt(0);
                                }

                                boaInfo.SlavePort = new uint[7];
                                for (int j = 0; j < camInfo.SlavePort.Length; j++)
                                {
                                    boaInfo.SlavePort[j] = camInfo.SlavePort[j];
                                }
                                m_hBoardL = IKapBoard.IKapOpenCXP((uint)BoardType.IKBoardPCIE, boaInfo.BoardIndex, boaInfo);
                                if (m_hBoardL.Equals(-1))
                                    CheckIKapBoard((int)ErrorCode.IKStatus_OpenBoardFail);
                                break;
                        }
                        if (configfil.LeftCameraConfigepath!=" ")
                        {
                           res= IKapCLib.ItkDevLoadConfigurationFromFile(m_hCameraL, configfil.LeftCameraConfigepath);
                            CheckIKapC(res);
                        }
                      
                        return;
                    }
                }
            }
            if (Manual == "Right")
            {
                for (uint i = 0; i < configfil.CameraNames.Count; i++)
                {
                    if (configfil.CameraNames[(int)i].SerialNumber == SerialNumber)
                    {
                        switch (configfil.CameraNames[(int)i].Camera_nType)
                        {
                            case 4:
                                res = IKapCLib.ItkDevOpen((uint)configfil.CameraNames[(int)i].Cameran_nDevIndex, (int)(ItkDeviceAccessMode.ITKDEV_VAL_ACCESS_MODE_CONTROL), ref m_hCameraR);
                                CheckIKapC(res);
                                break;
                            case 1:
                                res = IKapCLib.ItkDevOpen((uint)configfil.CameraNames[(int)i].Cameran_nDevIndex, (int)(ItkDeviceAccessMode.ITKDEV_VAL_ACCESS_MODE_CONTROL), ref m_hCameraR);
                                CheckIKapC(res);
                                m_hBoardR = IKapBoard.IKapOpen((uint)BoardType.IKBoardPCIE, (uint)configfil.CameraNames[(int)i].Camera_nBoardIndex);
                                if (m_hBoardR.Equals(-1))
                                    CheckIKapBoard((int)ErrorCode.IKStatus_OpenBoardFail);
                                break;
                            case 2:
                                res = IKapCLib.ItkDevOpen((uint)configfil.CameraNames[(int)i].Cameran_nDevIndex, (int)(ItkDeviceAccessMode.ITKDEV_VAL_ACCESS_MODE_CONTROL), ref m_hCameraR);
                                CheckIKapC(res);
                                IKapCLib.ITK_CXP_DEV_INFO camInfo = new IKapCLib.ITK_CXP_DEV_INFO();
                                IKapBoard.IKAP_CXP_BOARD_INFO boaInfo = new IKapBoard.IKAP_CXP_BOARD_INFO();
                                res = IKapCLib.ItkManGetCXPDeviceInfo((uint)i, ref camInfo);
                                CheckIKapC(res);
                                boaInfo.BoardIndex = camInfo.BoardIndex;
                                boaInfo.CameraIndex = camInfo.CameraId;
                                boaInfo.MasterPort = camInfo.MasterPort;
                                boaInfo.SlaveCount = camInfo.SlaveCount;

                                boaInfo.Reserved = new byte[252];
                                for (int j = 0; j < camInfo.Reserved.Length; j++)
                                {
                                    boaInfo.Reserved[j] = (byte)camInfo.Reserved.ElementAt(0);
                                }

                                boaInfo.SlavePort = new uint[7];
                                for (int j = 0; j < camInfo.SlavePort.Length; j++)
                                {
                                    boaInfo.SlavePort[j] = camInfo.SlavePort[j];
                                }
                                m_hBoardR = IKapBoard.IKapOpenCXP((uint)BoardType.IKBoardPCIE, boaInfo.BoardIndex, boaInfo);
                                if (m_hBoardR.Equals(-1))
                                    CheckIKapBoard((int)ErrorCode.IKStatus_OpenBoardFail);
                                break;
                        }
                        if (configfil.RightCameraConfigepath!=" ")
                        {
                           res= IKapCLib.ItkDevLoadConfigurationFromFile(m_hCameraR, configfil.RightCameraConfigepath);
                           CheckIKapC(res);
                        }
                        return;
                    }
                }
            }
        }
    }
}
